// vim:sw=4:ai:aw

#include "BestFit.h"
#include <cassert>
#include <iostream>

BestFit::BestFit() : Allocator("BestFit") {
    processes = new std::map<int,const Area*>;
    holes = 0;
}

BestFit::~BestFit() {
    processes->clear();
    holes->clear();
    delete processes;
    delete holes;
}

// iemand vraagt om 'wanted' geheugen
const Area * BestFit::alloc(int wanted) {
	assert(wanted > 0); // minstens "iets",
	assert(wanted <= size); // maar niet meer dan we kunnen hebben.
    assert(holes != 0); 

	const Area* area = 0;
	if (wanted <= size) {
        area = holes->getBestFittedHole(wanted);

        // return 0 als er geen vrije plek in de geheugen is
        if (area == 0) {
            return 0;
        }

        // is de gevonden hole groter dan wat wij willen hebben?
        if (area->getSize() > wanted) {
            // add remainder to holes lijst
            int base_remainder = area->getBase() + wanted;
            int size_remainder = area->getSize() - wanted;
            holes->insert(new Area(base_remainder, size_remainder));
            
            // change area size
            int base_newarea = area->getBase();
            delete area;
            area = new Area(base_newarea, wanted);
        }
	}

    assert(area != 0);
    processes->insert(std::make_pair(area->getBase(), area));

	return area;
}

// iemand levert een gebied weer in
void BestFit::free(const Area * area) {
    assert(area != 0);

    processes->erase(area->getBase());
    holes->insert(area);
}

void BestFit::setSize(int new_size) {
    assert(new_size >= 0);

    if (holes == 0) {
        holes = new LinkedList(new_size);
    }
    Allocator::setSize(new_size);
}
